home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagn_r.zip / POINTERS.SWG / 0015_Buffer Streams.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-25  |  6KB  |  177 lines

  1.  
  2. {
  3. JB> AS>Use buffered streams.  That way you can access fairly many records on
  4. JB> AS>disk without noticable speed degradation.
  5. JB>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  6. JB> Do you mean from RAM?? Whoah! How do you go about using buffered
  7. JB> streams?
  8.  
  9. Actually, you should write a local "cache" for your records.  Ie.,
  10. your implement an array of records, say 1..50, or, 1..MaxCacheSize,
  11. where MaxCacheSize is a defined constant.  Then you have a couple of
  12. generalized procedures for putting/getting records; now, the point is,
  13. whenever the program asks for a record -that is in the cache-, that
  14. record is read directly from RAM.  If the record is -not- in the
  15. cache, the record is read, and, if there is space in the cache, the
  16. record is inserted into the cache.
  17.  
  18. Let's try a Pascal implementation.
  19. }
  20.  
  21.         const
  22.           MaxCacheSize = 50; (* cache can hold 50 records *)
  23.  
  24.         type
  25.           (* this is the cache item *)
  26.           PCacheItem = ^TCacheItem;
  27.           TCacheItem =
  28.             record
  29.               Offset : Longint; (* file offset of cache record *)
  30.               Rec    : TRecord; (* use your own record type here *)
  31.             end;
  32.  
  33.         var
  34.           Cache : array[1..MaxCacheSize] of PCacheItem;
  35.           CacheSize : Word;
  36.  
  37.         procedure InitCache;
  38.           {-Resets cache}
  39.         begin
  40.           CacheSize:=0;
  41.         end;
  42.  
  43.         function FindCache (Offset : Longint) : PCacheItem;
  44.           {-Returns cache item for Offset if found, otherwise nil}
  45.         var
  46.           W : Word;
  47.         begin
  48.           for W:=1 to CacheSize do
  49.             if Cache[W]^.Offset = Offset then
  50.               begin
  51.                 FindCache:=Cache[W];
  52.                 Exit;
  53.               end;
  54.           FindCache:=nil;
  55.         end;
  56.  
  57.         var
  58.           F : file of TRecord; (* file in question *)
  59.  
  60.         procedure PutRecord (Offset : Longint; var Rec : TRecord);
  61.           {-Put record into cache and file}
  62.         var
  63.           P : PCacheItem;
  64.         begin
  65.           Write(F, Rec);
  66.  
  67.           (* if exists in RAM (cache), update it *)
  68.           P:=FindCache(Offset);
  69.           if P <> nil then
  70.             P^.Rec:=Rec
  71.           else
  72.             begin
  73.               (* put into cache *)
  74.               Inc(CacheSize);
  75.               New(Cache[CacheSize]);
  76.               Cache[CacheSize]^.Offset:=Offset;
  77.               Cache[CacheSize]^.Rec:=Rec;
  78.             end;
  79.         end;
  80.  
  81.         procedure GetRecord (Offset : Longint; var Rec : TRecord);
  82.           {-Get record from cached file}
  83.         var
  84.           P : PCacheItem;
  85.         begin
  86.           (* if exists in RAM (cache), get it *)
  87.           P:=FindCache(Offset);
  88.           if P <> nil then
  89.             Rec:=P^.Rec
  90.           else if CacheSize < MaxCacheSize then
  91.             begin
  92.               (* read record from file *)
  93.               Read(F, Rec);
  94.  
  95.               (* put into cache *)
  96.               Inc(CacheSize);
  97.               New(Cache[CacheSize]);
  98.               Cache[CacheSize]^.Offset:=Offset;
  99.               Cache[CacheSize]^.Rec:=Rec;
  100.             end;
  101.         end;
  102.  
  103. To use the routines:
  104.  
  105.           Assign(F, 'MYFILE.DAT');
  106.           Reset(F);
  107.           GetRecord(FilePos(F), MyRec);
  108.           GetRecord(FilePos(F), MyRec);
  109.           GetRecord(FilePos(F), MyRec);
  110.           PutRecord(FilePos(F), MyRec);
  111.           Close(F);
  112.  
  113. Or something like that, anyway.
  114.  
  115. Now, there is a simpler way; "simpler" in this case means "some guy
  116. has already spent hours writing it just for you".  The concept is
  117. called streams.  Now, I don't know how "novice" a programmer you are,
  118. but knowledge of streams requires knowledge of OOP.  I suggest you
  119. read about OOP right away.
  120.  
  121. Streams work in a very simple way.  You have a basic, "abstract"
  122. object, which provides some simple I/O tools.  A stream is a type of
  123. (abstract) file, an input/output mechanism, that you may manipulate;
  124. most often it's on a hierarchical level, ie., the high-level
  125. procedures call low-level procedures, just like DOS.  Think of streams
  126. as the Pascal type "file", except now the stream is a shell for
  127. anything.
  128.  
  129. The shell implements a -standard- interface for any kind of
  130. information area.  You have file streams, buffered streams (streams
  131. that caches areas of the file in memory to optimize access
  132. efficiency), EMS streams (yes, you can have a "virtual file" that lies
  133. in EMS memory and may be used just like a file), and so on.  The
  134. standardization implies that you may write more flexible programs.
  135.  
  136. A tiny example:
  137.  
  138.         var
  139.           S   : TBufStream;
  140.           T   : TRecord;
  141.           Str : string;
  142.         begin
  143.           S.Init('MYFILE.DAT', stOpen, 2048);
  144.               (* |             |          |
  145.                  file name     file mode  buffer size
  146.               *)
  147.           S.Read(T, SizeOf(T));
  148.           S.Write(T, SizeOf(T));
  149.           Str:=S.ReadStr^;
  150.  
  151.           S.Done;
  152.         end;
  153.  
  154. The corresponding boring-old-Dos example'd be:
  155.  
  156.         var
  157.           F   : file;
  158.           T   : TRecord;
  159.           Str : string;
  160.         begin
  161.           (* note: no buffering -> slower! *)
  162.           Assign(F, 'MYFILE.DAT');
  163.           Reset(F, 1);
  164.  
  165.           BlockRead(F, T, SizeOf(T));
  166.           BlockWrite(F, T, SizeOf(T));
  167.           Read(F, Str[0]);
  168.           BlockRead(F, Str[1], Ord(Str[0]));
  169.  
  170.           Close(F);
  171.         end;
  172.  
  173. In the end, streams -are- simpler, too.  And they are extremely fast;
  174. a friend of mine is writing a mail reader and is using object streams
  175. for the message/conference/etc. databases.  Now, personally I use
  176. indexed, light-speed B-tree databases.  And his work -just fine-.
  177.